using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Text;
using System.Xml;
using System.Xml.XPath;

namespace DBLGen
{
	[Editor(typeof(UI.Design.CustomAttributeEditor), typeof(System.Drawing.Design.UITypeEditor))]
	public sealed class CustomAttributes : IDictionary<string, string>
	{
		public CustomAttributes()
		{
			Items = new SortedDictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
		}

		private SortedDictionary<string, string> Items;

		#region IDictionary<string,string> Members

		public void Add(string key, string value)
		{
			Items.Add(key, value);
		}

		public bool ContainsKey(string key)
		{
			return Items.ContainsKey(key);
		}

		public ICollection<string> Keys
		{
			get
			{
				return Items.Keys;
			}
		}

		public bool Remove(string key)
		{
			return Items.Remove(key);
		}

		public bool TryGetValue(string key, out string value)
		{
			return Items.TryGetValue(key, out value);
		}

		public ICollection<string> Values
		{
			get
			{
				return Items.Values;
			}
		}

		public string this[string key]
		{
			get
			{
				if (Items.ContainsKey(key))
					return Items[key];
				else
					return null;
			}
			set
			{
				Items[key] = value;
			}
		}

		#endregion

		#region ICollection<KeyValuePair<string,string>> Members

		void ICollection<KeyValuePair<string, string>>.Add(KeyValuePair<string, string> item)
		{
			((ICollection<KeyValuePair<string, string>>)Items).Add(item);
		}

		public void Clear()
		{
			Items.Clear();
		}

		bool ICollection<KeyValuePair<string, string>>.Contains(KeyValuePair<string, string> item)
		{
			return ((ICollection<KeyValuePair<string, string>>)Items).Contains(item);
		}

		public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
		{
			Items.CopyTo(array, arrayIndex);
		}

		public int Count
		{
			get
			{
				return Items.Count;
			}
		}

		bool ICollection<KeyValuePair<string, string>>.IsReadOnly
		{
			get
			{
				return false;
			}
		}

		bool ICollection<KeyValuePair<string, string>>.Remove(KeyValuePair<string, string> item)
		{
			return ((ICollection<KeyValuePair<string, string>>)Items).Remove(item);
		}

		#endregion

		#region IEnumerable<KeyValuePair<string,string>> Members

		public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
		{
			return ((ICollection<KeyValuePair<string, string>>)Items).GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		IEnumerator IEnumerable.GetEnumerator()
		{
			return Items.GetEnumerator();
		}

		#endregion

		#region Clone

		public CustomAttributes Clone()
		{
			CustomAttributes ca = new CustomAttributes();

			foreach (string key in this.Keys)
			{
				ca[key] = this[key];
			}

			return ca;
		}

		#endregion

		public override string ToString()
		{
			return Items.Count + " attributes defined";
		}

		#region Xml Persistence

		internal static CustomAttributes LoadXml(XPathNavigator navigator)
		{
			CustomAttributes ca = new CustomAttributes();

			XPathNodeIterator ni = navigator.Select("customAttributes/attribute");

			while (ni.MoveNext())
			{
				XPathNavigator current = ni.Current;

				string key = current.GetAttribute("name", current.NamespaceURI);
				string value = current.Value.Replace("\n", Environment.NewLine);

				ca[key] = value;
			}

			return ca;
		}

		internal void SaveXml(XmlWriter writer)
		{
			if (Items.Count > 0)
			{
				writer.WriteStartElement("customAttributes");

				foreach (KeyValuePair<string, string> kvp in this)
				{
					writer.WriteStartElement("attribute");
					writer.WriteAttributeString("name", kvp.Key);

					if (!String.IsNullOrEmpty(kvp.Value))
						writer.WriteCData(kvp.Value);

					writer.WriteEndElement();
				}

				writer.WriteEndElement();
			}
		}

		#endregion
	}
}
